using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using Microsoft.SharePoint;
using System.Web.Security;
using Microsoft.SharePoint.WebControls;

namespace By1eEurope.BKS.Controls
{
    /// <summary>
    /// Decides based on a bool'sch expression about the membership of the current user
    /// </summary>
    public class MembershipAnalyser : IExpressionAnalyser
    {
        #region IExpressionAnalyser Members

        public bool AnalyseExpression(string expression, HttpRequest request, HttpContext context)
        {
            //If current is Anonym
            if (!context.User.Identity.IsAuthenticated) // If Anonym
            {
                if (expression.ToLower() == "anonym")
                    return true;
                else
                    return false;
            }

            //Auth users never match with 'anonym'
            if (expression.ToLower() == "anonym")
                return false;

            //If current is Auth
            bool ret = false;
            SPUser u = SPContext.Current.Web.CurrentUser;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SPControl.GetContextSite(context).Url))
                {
                    using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl))
                    {
                        if (u != null)
                        {
                            string[] terms = expression.Split(new char[] { '+' }, StringSplitOptions.RemoveEmptyEntries);

                            bool or = false; //neutralelemnt of OR operation
                            foreach (string term in terms)
                            {
                                string[] groups = term.Split(new char[] { '*' }, StringSplitOptions.RemoveEmptyEntries);
                                bool and = true; // neutralelement of AND operation
                                foreach (string group in groups)
                                {

                                    string group2 = group;
                                    bool invert = false;
                                    if (group.StartsWith("!"))
                                    {
                                        group2 = group.Substring(1);
                                        invert = true;
                                    }

                                    try
                                    {
                                        SPGroup dummy = u.Groups[group2];
                                        and &= true;
                                    }
                                    catch
                                    {
                                        bool andTmp = false;
                                        if (Membership.Provider.ToString() == "Migros.MembershipExtensions.MGBMembershipProvider")   // Check, if FBA Role of User is in the group
                                        {
                                            string[] roles = Roles.GetRolesForUser();
                                            try
                                            {
                                                SPGroup spGroup = site.RootWeb.Groups[group2];
                                                foreach (string role in roles)
                                                {
                                                    try
                                                    {
                                                        string fullRoleName = Roles.Provider.Name + ":" + role;
                                                        SPUser dummy = spGroup.Users[fullRoleName.ToLower()];
                                                        andTmp = true;
                                                        break;
                                                    }
                                                    catch { }
                                                }
                                            }
                                            catch { }
                                        }
                                        and &= andTmp;
                                    }

                                    if (invert)
                                        and = !and;

                                }
                                or |= and;
                            }
                            ret = or;
                        }
                    }
                    if (site.RootWeb != null)
                        site.RootWeb.Dispose();
                }
            });
            return ret;
        }

        #endregion
    }
}
